/**
 * Trabajo de Ingeniería de Software 2
 * Año 2008
 * Sistema de Reserva de Recursos.
 * Desarrolladores: - Marcelo Ferreira.
 *                  - Christian Gómez.
 *                  - Marcelo Rodas.
 */
package controller;

import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.faces.application.FacesMessage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.faces.FacesException;
import java.util.HashMap;
import javax.faces.validator.ValidatorException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Vector;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;
import modelo.Datospersonales;
import modelo.Solicitudusuario;
import modelo.Usuario;

/**
 * Controlador de las Funcionalidades de DatosPersonales.
 * Utilizado para manejar la capa de controlador (MVC)
 * del sistema.
 * @author cgomez
 * @version 1.0
 */
public class DatospersonalesController {

    // POJO de DatosPersonales Representada.
    private Datospersonales datospersonales = null;
    // Lista de DatosPersonales
    private List<Datospersonales> datospersonaless = null;
    // Transacción del usuario.
    @Resource
    private UserTransaction utx = null;
    // Administrador de la Persistencia de los DatosPersonales.
    // Relaciona al Controlador con el Modelo (MVC)
    @PersistenceUnit(unitName = "sistemaReservaPU")
    private EntityManagerFactory emf = null;
    //Variables para manejo de fechas en los formatos dd/mm/yyyy hh:mm
    DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    /**
     * Getter del Administrador de Entidades.
     * @return EntityManager
     */
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
    
    // ---------- Variables para paginar en el jsp -------------
    // variable auxiliar que indica el tamaño de conjunto
    public int batchSize = 100;
    // variable auxiliar para indicar el 1er elemento
    private int firstItem = 0;
    // variable auxiliar utilizado como contador de elementos
    private int itemCount = -1;
    // ---------------------------------------------------------

    /**
     * Setter del Usuario de los DatosPersonales
     * @param usuarioCollection coleccion de usuarios
     */
    public void setUsuarioCollectionOfDatospersonales(Usuario[] usuarioCollection) {
        List<Usuario> usuarioCollectionList = Arrays.asList(usuarioCollection);
        datospersonales.setUsuarioCollection(usuarioCollectionList);
    }

    /**
     * Getter del Usuario de los DatosPersonales
     * @return colleccion de Usuarios
     */
    public Usuario[] getUsuarioCollectionOfDatospersonales() {
        Collection<Usuario> usuarioCollection = datospersonales.getUsuarioCollection();
        if (usuarioCollection == null) {
            return new Usuario[0];
        }
        return usuarioCollection.toArray(new Usuario[0]);
    }

    /**
     * Setter del Solicitud de los DatosPersonales
     * @param solicitudusuarioCollection
     */
    public void setSolicitudusuarioCollectionOfDatospersonales(Solicitudusuario[] solicitudusuarioCollection) {
        List<Solicitudusuario> solicitudusuarioCollectionList = Arrays.asList(solicitudusuarioCollection);
        datospersonales.setSolicitudusuarioCollection(solicitudusuarioCollectionList);
    }

    /**
     * Getter del Solicitudes de los DatosPersonales
     * @return solicitudusuarioCollection.toArray(new Solicitudusuario[0])
     */
    public Solicitudusuario[] getSolicitudusuarioCollectionOfDatospersonales() {
        Collection<Solicitudusuario> solicitudusuarioCollection = datospersonales.getSolicitudusuarioCollection();
        if (solicitudusuarioCollection == null) {
            return new Solicitudusuario[0];
        }
        return solicitudusuarioCollection.toArray(new Solicitudusuario[0]);
    }

    /**
     * Metodo para obtener una lista de los DatosPersonales disponibles de varias selecciones
     * @return lista de DatosPersonales
     */
    public SelectItem[] getDatospersonalessAvailableSelectMany() {
        return getDatospersonalessAvailable(false);
    }

    /**
     * Metodo publico para obtener una lista de los DatosPersonales disponibles de una sola seleccion
     * @return lista de DatosPersonales
     */
    public SelectItem[] getDatospersonalessAvailableSelectOne() {
        return getDatospersonalessAvailable(true);
    }

    /**
     * Metodo privado para obtener una lista de los DatosPersonales disponibles de una sola seleccion
     * @return lista de DatosPersonales
     */
    private SelectItem[] getDatospersonalessAvailable(boolean one) {
        List<Datospersonales> allDatospersonaless = getDatospersonaless(true);
        int size = one ? allDatospersonaless.size() + 1 : allDatospersonaless.size();
        SelectItem[] items = new SelectItem[size];
        int i = 0;
        if (one) {
            items[0] = new SelectItem("", "---");
            i++;
        }
        for (Datospersonales x : allDatospersonaless) {
            items[i++] = new SelectItem(x, x.toString());
        }
        return items;
    }

    /**
     * Metodo para obtener el objeto DatosPersonales del Request
     * @return el objeto DatosPersonales obtenido
     */
    public Datospersonales getDatospersonales() {
        if (datospersonales == null) {
            datospersonales = getDatospersonalesFromRequest();
        }
        if (datospersonales == null) {
            datospersonales = new Datospersonales();
        }
        return datospersonales;
    }

    /**
     * Metodo para resetear los valores de inicio y llamar al Tag de Lista de Datos personales
     * @return el tag de la Lista de Datos personales
     */
    public String listSetup() {
        reset(true);
        return "datospersonales_list";
    }

    /**
     * Metodo para inicializar los valores del Objeto DatosPersonales para un nuevo objeto
     * @return el Tag del JSP para crear una nueva entrada de DatosPersonles
     */
    public String createSetup() {
        reset(false);
        datospersonales = new Datospersonales(this.getItemMax());
        return "datospersonales_create";
    }

    /**
     * Metodo publico para crear una nueva entrada de DatosPersonales
     * @return el Tag del siguiente JSP a desplegar
     */
    public String create() {
        
        try{
            Date fnacimiento = dateFormat.parse(this.getRequestParameter("fechanacimiento"));
            datospersonales.setFechaNacimiento(fnacimiento);
        }catch(Exception e){
           addErrorMessage("La fecha seleccionada es invalida");
           return null;
        }
        if (datospersonales.getUsuarioCollection() == null) {
            datospersonales.setUsuarioCollection(new ArrayList<Usuario>());
        }
        if (datospersonales.getSolicitudusuarioCollection() == null) {
            datospersonales.setSolicitudusuarioCollection(new ArrayList<Solicitudusuario>());
        }
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            List<Usuario> attachedUsuarioCollection = new ArrayList<Usuario>();
            for (Usuario usuarioCollectionUsuarioToAttach : datospersonales.getUsuarioCollection()) {
                usuarioCollectionUsuarioToAttach = em.getReference(usuarioCollectionUsuarioToAttach.getClass(), usuarioCollectionUsuarioToAttach.getIdUsuario());
                attachedUsuarioCollection.add(usuarioCollectionUsuarioToAttach);
            }
            datospersonales.setUsuarioCollection(attachedUsuarioCollection);
            List<Solicitudusuario> attachedSolicitudusuarioCollection = new ArrayList<Solicitudusuario>();
            for (Solicitudusuario solicitudusuarioCollectionSolicitudusuarioToAttach : datospersonales.getSolicitudusuarioCollection()) {
                solicitudusuarioCollectionSolicitudusuarioToAttach = em.getReference(solicitudusuarioCollectionSolicitudusuarioToAttach.getClass(), solicitudusuarioCollectionSolicitudusuarioToAttach.getIdsolicitudusuario());
                attachedSolicitudusuarioCollection.add(solicitudusuarioCollectionSolicitudusuarioToAttach);
            }
            datospersonales.setSolicitudusuarioCollection(attachedSolicitudusuarioCollection);
            em.persist(datospersonales);
            for (Usuario usuarioCollectionUsuario : datospersonales.getUsuarioCollection()) {
                Datospersonales oldIddatospersonalesOfUsuarioCollectionUsuario = usuarioCollectionUsuario.getIddatospersonales();
                usuarioCollectionUsuario.setIddatospersonales(datospersonales);
                usuarioCollectionUsuario = em.merge(usuarioCollectionUsuario);
                if (oldIddatospersonalesOfUsuarioCollectionUsuario != null) {
                    oldIddatospersonalesOfUsuarioCollectionUsuario.getUsuarioCollection().remove(usuarioCollectionUsuario);
                    oldIddatospersonalesOfUsuarioCollectionUsuario = em.merge(oldIddatospersonalesOfUsuarioCollectionUsuario);
                }
            }
            for (Solicitudusuario solicitudusuarioCollectionSolicitudusuario : datospersonales.getSolicitudusuarioCollection()) {
                Datospersonales oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario = solicitudusuarioCollectionSolicitudusuario.getIddatospersonales();
                solicitudusuarioCollectionSolicitudusuario.setIddatospersonales(datospersonales);
                solicitudusuarioCollectionSolicitudusuario = em.merge(solicitudusuarioCollectionSolicitudusuario);
                if (oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario != null) {
                    oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario.getSolicitudusuarioCollection().remove(solicitudusuarioCollectionSolicitudusuario);
                    oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario = em.merge(oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario);
                }
            }
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            Usuario usuarioLogeado = (Usuario) session.getAttribute("user");
            datospersonales.setUserAudita(usuarioLogeado.getIdUsuario());

            utx.commit();
            addSuccessMessage("El nuevo registro de datos personales fue creado con éxito.");
        } catch (Exception ex) {
            try {
                if (findDatospersonales(datospersonales.getIddatospersonales()) != null) {
                    addErrorMessage("El registo " + datospersonales + " ya existe.");
                } else {
                    ensureAddErrorMessage(ex, "Ha ocurrido un error en la bases de datos.");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Ocurrió un error al intentar restaurar la transacción.");
            }
            return null;
        } finally {
            em.close();
        }
        return listSetup();
    }


    /**
     * Funcion de Navegacion a la Pagina Detail.jsp de los DatosPersonales
     * @return String
     */
    public String detailSetup() {
        return scalarSetup("datospersonales_detail");
    }
    
    /**
     * Funcion de Navegacion a la Pagina DetailS.jsp de los DatosPersonales
     * @return String
     */
    public String detailSetup2() {
        return scalarSetup("datospersonales_detail2");
    }
    
    /**
     * Funcion de Navegacion a la Pagina Edit.jsp de los DatosPersonales
     * @return String
     */
    public String editSetup() {
        return scalarSetup("datospersonales_edit");
    }
   /**
    * Funcion de Navegacion a la Pagina Edit.jsp de los DatosPersonales para Solicitud de Acceso
    * @return String
    */
    public String editSetupSolicitante() {
        return scalarSetup("datospersonales_editsolicitante");
    }

    /**
     * Función de Navegación General, controla si existe la ruta de navegación.
     * @param destination
     * @return String
     */
    private String scalarSetup(String destination) {
        reset(false);
        datospersonales = getDatospersonalesFromRequest();
        if (datospersonales == null) {
            String requestDatospersonalesString = getRequestParameter("jsfcrud.currentDatospersonales");
            addErrorMessage("El registro con el id " + requestDatospersonalesString + " ya no existe.");
            String relatedControllerOutcome = relatedControllerOutcome();
            if (relatedControllerOutcome != null) {
                return relatedControllerOutcome;
            }
            return listSetup();
        }
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        Usuario usuarioLogeado = (Usuario) session.getAttribute("user");
        datospersonales.setUserAudita(usuarioLogeado.getIdUsuario());
        return destination;
    }
    
    /**
     * Función privada que procesa los cambios realizados sobre los
     * DatosPersonales Representados.
     * @return String
     */
    private String editar() {
        DatospersonalesConverter converter = new DatospersonalesConverter();
        String datospersonalesString = converter.getAsString(FacesContext.getCurrentInstance(), null, datospersonales);
        String currentDatospersonalesString = getRequestParameter("jsfcrud.currentDatospersonales");
        if (datospersonalesString == null || datospersonalesString.length() == 0 || !datospersonalesString.equals(currentDatospersonalesString)) {
            String outcome = editSetup();
            if ("datospersonales_edit".equals(outcome)) {
                addErrorMessage("No se puede editar los datos personales. Intente nuevamente.");
            }
            return outcome;
        }
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            Datospersonales persistentDatospersonales = em.find(Datospersonales.class, datospersonales.getIddatospersonales());
            Collection<Usuario> usuarioCollectionOld = persistentDatospersonales.getUsuarioCollection();
            Collection<Usuario> usuarioCollectionNew = datospersonales.getUsuarioCollection();
            Collection<Solicitudusuario> solicitudusuarioCollectionOld = persistentDatospersonales.getSolicitudusuarioCollection();
            Collection<Solicitudusuario> solicitudusuarioCollectionNew = datospersonales.getSolicitudusuarioCollection();
            List<Usuario> attachedUsuarioCollectionNew = new ArrayList<Usuario>();
            for (Usuario usuarioCollectionNewUsuarioToAttach : usuarioCollectionNew) {
                usuarioCollectionNewUsuarioToAttach = em.getReference(usuarioCollectionNewUsuarioToAttach.getClass(), usuarioCollectionNewUsuarioToAttach.getIdUsuario());
                attachedUsuarioCollectionNew.add(usuarioCollectionNewUsuarioToAttach);
            }
            usuarioCollectionNew = attachedUsuarioCollectionNew;
            datospersonales.setUsuarioCollection(usuarioCollectionNew);
            List<Solicitudusuario> attachedSolicitudusuarioCollectionNew = new ArrayList<Solicitudusuario>();
            for (Solicitudusuario solicitudusuarioCollectionNewSolicitudusuarioToAttach : solicitudusuarioCollectionNew) {
                solicitudusuarioCollectionNewSolicitudusuarioToAttach = em.getReference(solicitudusuarioCollectionNewSolicitudusuarioToAttach.getClass(), solicitudusuarioCollectionNewSolicitudusuarioToAttach.getIdsolicitudusuario());
                attachedSolicitudusuarioCollectionNew.add(solicitudusuarioCollectionNewSolicitudusuarioToAttach);
            }
            solicitudusuarioCollectionNew = attachedSolicitudusuarioCollectionNew;
            datospersonales.setSolicitudusuarioCollection(solicitudusuarioCollectionNew);
            datospersonales = em.merge(datospersonales);
            for (Usuario usuarioCollectionOldUsuario : usuarioCollectionOld) {
                if (!usuarioCollectionNew.contains(usuarioCollectionOldUsuario)) {
                    usuarioCollectionOldUsuario.setIddatospersonales(null);
                    usuarioCollectionOldUsuario = em.merge(usuarioCollectionOldUsuario);
                }
            }
            for (Usuario usuarioCollectionNewUsuario : usuarioCollectionNew) {
                if (!usuarioCollectionOld.contains(usuarioCollectionNewUsuario)) {
                    Datospersonales oldIddatospersonalesOfUsuarioCollectionNewUsuario = usuarioCollectionNewUsuario.getIddatospersonales();
                    usuarioCollectionNewUsuario.setIddatospersonales(datospersonales);
                    usuarioCollectionNewUsuario = em.merge(usuarioCollectionNewUsuario);
                    if (oldIddatospersonalesOfUsuarioCollectionNewUsuario != null && !oldIddatospersonalesOfUsuarioCollectionNewUsuario.equals(datospersonales)) {
                        oldIddatospersonalesOfUsuarioCollectionNewUsuario.getUsuarioCollection().remove(usuarioCollectionNewUsuario);
                        oldIddatospersonalesOfUsuarioCollectionNewUsuario = em.merge(oldIddatospersonalesOfUsuarioCollectionNewUsuario);
                    }
                }
            }
            for (Solicitudusuario solicitudusuarioCollectionOldSolicitudusuario : solicitudusuarioCollectionOld) {
                if (!solicitudusuarioCollectionNew.contains(solicitudusuarioCollectionOldSolicitudusuario)) {
                    solicitudusuarioCollectionOldSolicitudusuario.setIddatospersonales(null);
                    solicitudusuarioCollectionOldSolicitudusuario = em.merge(solicitudusuarioCollectionOldSolicitudusuario);
                }
            }
            for (Solicitudusuario solicitudusuarioCollectionNewSolicitudusuario : solicitudusuarioCollectionNew) {
                if (!solicitudusuarioCollectionOld.contains(solicitudusuarioCollectionNewSolicitudusuario)) {
                    Datospersonales oldIddatospersonalesOfSolicitudusuarioCollectionNewSolicitudusuario = solicitudusuarioCollectionNewSolicitudusuario.getIddatospersonales();
                    solicitudusuarioCollectionNewSolicitudusuario.setIddatospersonales(datospersonales);
                    solicitudusuarioCollectionNewSolicitudusuario = em.merge(solicitudusuarioCollectionNewSolicitudusuario);
                    if (oldIddatospersonalesOfSolicitudusuarioCollectionNewSolicitudusuario != null && !oldIddatospersonalesOfSolicitudusuarioCollectionNewSolicitudusuario.equals(datospersonales)) {
                        oldIddatospersonalesOfSolicitudusuarioCollectionNewSolicitudusuario.getSolicitudusuarioCollection().remove(solicitudusuarioCollectionNewSolicitudusuario);
                        oldIddatospersonalesOfSolicitudusuarioCollectionNewSolicitudusuario = em.merge(oldIddatospersonalesOfSolicitudusuarioCollectionNewSolicitudusuario);
                    }
                }
            }
            utx.commit();
            addSuccessMessage("El registro ha sido actualizado con éxito.");
        } catch (Exception ex) {
            try {
                String msg = ex.getLocalizedMessage();
                if (msg != null && msg.length() > 0) {
                    addErrorMessage(msg);
                } else if (getDatospersonalesFromRequest() == null) {
                    addErrorMessage("El registro con el id " + currentDatospersonalesString + " ya no existe.");
                    utx.rollback();
                    return listSetup();
                } else {
                    addErrorMessage("Ha ocurrido un error en la bases de datos..");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Ocurrió un error al intentar restaurar la transacción.");
            }
            return null;
        } finally {
            em.close();
        }
        return listSetup();
    }
    
    /**
     * Función publica que procesa los cambios realizados sobre los
     * DatosPersonales Representados.
     * @return String
     */
    public String edit(){
        return editar();
    }
    
    /**
     * Función publica que procesa los cambios realizados sobre los
     * DatosPersonales de cada propietario.
     * @return String
     */
    
    public String editMySelf(){
        String resultado = editar();
        if (resultado == null)
            return null;
        else if (resultado.equals("datospersonales_edit"))
            return resultado;
        else
            return "menuAdminPerfil";
    }
    /**
     * Función publica que procesa los cambios realizados sobre los
     * DatosPersonales de cada propietario.
     * @return String
     */
    public String editSolicitante(){
        String resultado = editar();
        if (resultado == null)
            return null;
        else if (resultado.equals("datospersonales_edit"))
            return resultado;
        else
            return "usuarioSolicitante_list";
    }
    
    /**
     * Funcion que permite la eliminacion de una entrada de DatosPersonales
     * @return String
     */
    public String destroy() {
        datospersonales = getDatospersonalesFromRequest();
        if (datospersonales == null) {
            String currentDatospersonalesString = getRequestParameter("jsfcrud.currentDatospersonales");
            addErrorMessage("El registro con el id " + currentDatospersonalesString + " ya no existe.");
            String relatedControllerOutcome = relatedControllerOutcome();
            if (relatedControllerOutcome != null) {
                return relatedControllerOutcome;
            }
            return listSetup();
        }
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            datospersonales = em.getReference(datospersonales.getClass(), datospersonales.getIddatospersonales());
            Collection<Usuario> usuarioCollection = datospersonales.getUsuarioCollection();
            for (Usuario usuarioCollectionUsuario : usuarioCollection) {
                usuarioCollectionUsuario.setIddatospersonales(null);
                usuarioCollectionUsuario = em.merge(usuarioCollectionUsuario);
            }
            Collection<Solicitudusuario> solicitudusuarioCollection = datospersonales.getSolicitudusuarioCollection();
            for (Solicitudusuario solicitudusuarioCollectionSolicitudusuario : solicitudusuarioCollection) {
                solicitudusuarioCollectionSolicitudusuario.setIddatospersonales(null);
                solicitudusuarioCollectionSolicitudusuario = em.merge(solicitudusuarioCollectionSolicitudusuario);
            }
            em.remove(datospersonales);
            utx.commit();
            addSuccessMessage("El registro ha sido borrado.");
        } catch (Exception ex) {
            try {
                ensureAddErrorMessage(ex, "Ha ocurrido un error en la base de datos.");
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Ocurrió un error al intentar restaurar la transacción.");
            }
            return null;
        } finally {
            em.close();
        }
        String relatedControllerOutcome = relatedControllerOutcome();
        if (relatedControllerOutcome != null) {
            return relatedControllerOutcome;
        }
        return listSetup();
    }

    /**
     * Función privada para obtener el Objeto DatosPersonales del Request.
     * @return Datospersonales
     */
    private Datospersonales getDatospersonalesFromRequest() {
        String theId = getRequestParameter("jsfcrud.currentDatospersonales");
        return (Datospersonales) new DatospersonalesConverter().getAsObject(FacesContext.getCurrentInstance(), null, theId);
    }

    /**
     * Función para obtener un valor del request.
     * @param key
     * @return String
     */
    private String getRequestParameter(String key) {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);
    }
    
    /**
     * Getter de DatosPersonales (atributo local).
     * @return List<DatosPersonales>
     */
    public List<Datospersonales> getDatospersonaless() {
        if (datospersonaless == null) {
            datospersonaless = getDatospersonaless(false);
        }
        return datospersonaless;
    }
    
    /**
     * Getter de todos los DatosPersonales (de la Base de Datos)
     * @param all
     * @return List<DatosPersonales>
     */
    public List<Datospersonales> getDatospersonaless(boolean all) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Datospersonales as o");
            if (!all) {
                q.setMaxResults(batchSize);
                q.setFirstResult(getFirstItem());
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    /*
     *-------------------------------------------------------------------
     * Funciones de manejo de Mensajes y Errores.
     *-------------------------------------------------------------------
     */
    
    /**
     * Asegura que se almacenen los errores
     * @param ex
     * @param defaultMsg
     */
    private void ensureAddErrorMessage(Exception ex, String defaultMsg) {
        String msg = ex.getLocalizedMessage();
        if (msg != null && msg.length() > 0) {
            addErrorMessage(msg);
        } else {
            addErrorMessage(defaultMsg);
        }
    }
    
    /**
     * Agrega mensajes de Error para la Página.
     * @param msg
     */
    public static void addErrorMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
    }

    /**
     * Agrega mensajes de Exito para la Página.
     * @param msg
     */
    public static void addSuccessMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
        FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);
    }

    /**
     * Obtiene un Objeto DatosPersonales con el id correspondiente.
     * @param id idDatosPersonales
     * @return o Objeto DatosPersoneles
     */
    public Datospersonales findDatospersonales(Integer id) {
        EntityManager em = getEntityManager();
        try {
            Datospersonales o = (Datospersonales) em.find(Datospersonales.class, id);
            return o;
        } finally {
            em.close();
        }
    }
    
    /**
     * ------------------------------------------
     * Funciones de Iteración
     * ------------------------------------------
     */
    
    /**
     * Funcion para obtener una cuenta de todos los items de esta clase
     * @return int
     */
    public int getItemCount() {
        if (itemCount == -1) {
            EntityManager em = getEntityManager();
            try {
                itemCount = ((Long) em.createQuery("select count(o) from Datospersonales as o").getSingleResult()).intValue();
            } finally {
                em.close();
            }
        }
        return itemCount;
    }
    
    /**
     * Funcion para obtener el primer item de esta clase
     * @return int
     */
    public int getFirstItem() {
        getItemCount();
        if (firstItem >= itemCount) {
            if (itemCount == 0) {
                firstItem = 0;
            } else {
                int zeroBasedItemCount = itemCount - 1;
                double pageDouble = zeroBasedItemCount / batchSize;
                int page = (int) Math.floor(pageDouble);
                firstItem = page * batchSize;
            }
        }
        return firstItem;
    }
    
    /**
     * Funcion para obtener el ultimo item de esta clase
     * @return int
     */
    public int getLastItem() {
        getFirstItem();
        return firstItem + batchSize > itemCount ? itemCount : firstItem + batchSize;
    }
    
    /**
     * Funcion para obtener el tamaño de datos a desplegar de esta clase
     * @return int
     */
    public int getBatchSize() {
        return batchSize;
    }
    
    /**
     * Funcion para obtener el siguiente item de esta clase
     * @return int
     */
    public String next() {
        reset(false);
        getFirstItem();
        if (firstItem + batchSize < itemCount) {
            firstItem += batchSize;
        }
        return "datospersonales_list";
    }
    
    /**
     * Funcion para obtener el item anterior de esta clase
     * @return int
     */
    public String prev() {
        reset(false);
        getFirstItem();
        firstItem -= batchSize;
        if (firstItem < 0) {
            firstItem = 0;
        }
        return "datospersonales_list";
    }
    
    /**
     * Funcion para saber de que contexto esta viniendo la peticion
     * @return String
     */
    private String relatedControllerOutcome() {
        String relatedControllerString = getRequestParameter("jsfcrud.relatedController");
        String relatedControllerTypeString = getRequestParameter("jsfcrud.relatedControllerType");
        if (relatedControllerString != null && relatedControllerTypeString != null) {
            FacesContext context = FacesContext.getCurrentInstance();
            Object relatedController = context.getApplication().getELResolver().getValue(context.getELContext(), null, relatedControllerString);
            try {
                Class<?> relatedControllerType = Class.forName(relatedControllerTypeString);
                Method detailSetupMethod = relatedControllerType.getMethod("detailSetup");
                return (String) detailSetupMethod.invoke(relatedController);
            } catch (ClassNotFoundException e) {
                throw new FacesException(e);
            } catch (NoSuchMethodException e) {
                throw new FacesException(e);
            } catch (IllegalAccessException e) {
                throw new FacesException(e);
            } catch (InvocationTargetException e) {
                throw new FacesException(e);
            }
        }
        return null;
    }

    /**
     * Borra la referencia al objeto Representado (Borrado sin persistencia).
     * @param resetFirstItem
     */
    private void reset(boolean resetFirstItem) {
        datospersonales = null;
        datospersonaless = null;
        itemCount = -1;
        if (resetFirstItem) {
            firstItem = 0;
        }
    }
    private Map<Object, String> asString = null;
    
    /**
     * Mapea el tipo de Objeto a un tipo String
     * @return Map<Object, String>
     */
    public Map<Object, String> getAsString() {
        if (asString == null) {
            asString = new HashMap<Object, String>() {

                @Override
                public String get(Object key) {
                    if (key instanceof Object[]) {
                        Object[] keyAsArray = (Object[]) key;
                        if (keyAsArray.length == 0) {
                            return "(No Items)";
                        }
                        StringBuffer sb = new StringBuffer();
                        for (int i = 0; i < keyAsArray.length; i++) {
                            if (i > 0) {
                                sb.append("<br />");
                            }
                            sb.append(keyAsArray[i]);
                        }
                        return sb.toString();
                    }
                    return new DatospersonalesConverter().getAsString(FacesContext.getCurrentInstance(), null, (Datospersonales) key);
                }
            };
        }
        return asString;
    }
    
    /**
     * Función que Vincula y Valida JSP con el Objeto DatosPersonales Representado.
     * @param facesContext
     * @param component
     * @param value
     */
    public void validateCreate(FacesContext facesContext, UIComponent component, Object value) {
        DatospersonalesConverter converter = new DatospersonalesConverter();
        String newDatospersonalesString = converter.getAsString(FacesContext.getCurrentInstance(), null, new Datospersonales());
        String datospersonalesString = converter.getAsString(FacesContext.getCurrentInstance(), null, datospersonales);
        if (!newDatospersonalesString.equals(datospersonalesString)) {
            createSetup();
        }
    }
    
    /**
     * Metodo para inicializar los valores del Objeto DatosPersonales para un nuevo objeto
     * @return el Tag del JSP para crear una nueva Solicitud de Acceso
     */
    public String createSetupS() {
        reset(false);
        datospersonales = new Datospersonales(this.getItemMax());
        return "solicitudusuarios";
    }

    /**
     * Metodo para obtener el mayor valor del ID DatosPersonales de la DB
     * @return Int
     */
    public int getItemMax() {
        EntityManager em = getEntityManager();
        String SQL;
        Integer s = 0;
        try {
            SQL = "select f_generar_iddatospersonales()";
            Query q = em.createNativeQuery(SQL);
            Vector v = new Vector();
            v = (Vector) q.getSingleResult();
            s = (Integer) v.get(0);
        } finally {
            em.close();
        }
        return s;
    }
    
    /**
     * Metodo para validar los parametros iniciales para una nueva solicitud de acceso
     * @param facesContext
     * @param component
     * @param value
     */
    public void validateCreateS(FacesContext facesContext, UIComponent component, Object value) {
        DatospersonalesConverter converter = new DatospersonalesConverter();
        String newDatospersonalesString = converter.getAsString(FacesContext.getCurrentInstance(), null, new Datospersonales());
        String datospersonalesString = converter.getAsString(FacesContext.getCurrentInstance(), null, datospersonales);
        if (!newDatospersonalesString.equals(datospersonalesString)) {
            createSetupS();
        }
    }
    
    /**
     * Metodo publico para crear una nueva entrada de Solicitud de Acceso
     * @return el Tag del siguiente JSP a desplegar
     */
    public String createS() {
            
        try{
            Date fnacimiento = dateFormat.parse(this.getRequestParameter("fechanacimiento"));
            datospersonales.setFechaNacimiento(fnacimiento);
        }catch(Exception e){
           addErrorMessage("La fecha seleccionada es invalida");
           return null;
        }
        if (datospersonales.getUsuarioCollection() == null) {
            datospersonales.setUsuarioCollection(new ArrayList<Usuario>());
        }
        if (datospersonales.getSolicitudusuarioCollection() == null) {
            datospersonales.setSolicitudusuarioCollection(new ArrayList<Solicitudusuario>());
        }

        EntityManager em = getEntityManager();
        try {
            utx.begin();
            List<Usuario> attachedUsuarioCollection = new ArrayList<Usuario>();
            for (Usuario usuarioCollectionUsuarioToAttach : datospersonales.getUsuarioCollection()) {
                usuarioCollectionUsuarioToAttach = em.getReference(usuarioCollectionUsuarioToAttach.getClass(), usuarioCollectionUsuarioToAttach.getIdUsuario());
                attachedUsuarioCollection.add(usuarioCollectionUsuarioToAttach);
            }
            datospersonales.setUsuarioCollection(attachedUsuarioCollection);
            List<Solicitudusuario> attachedSolicitudusuarioCollection = new ArrayList<Solicitudusuario>();
            for (Solicitudusuario solicitudusuarioCollectionSolicitudusuarioToAttach : datospersonales.getSolicitudusuarioCollection()) {
                solicitudusuarioCollectionSolicitudusuarioToAttach = em.getReference(solicitudusuarioCollectionSolicitudusuarioToAttach.getClass(), solicitudusuarioCollectionSolicitudusuarioToAttach.getIdsolicitudusuario());
                attachedSolicitudusuarioCollection.add(solicitudusuarioCollectionSolicitudusuarioToAttach);
            }
            datospersonales.setSolicitudusuarioCollection(attachedSolicitudusuarioCollection);
            em.persist(datospersonales);
            for (Usuario usuarioCollectionUsuario : datospersonales.getUsuarioCollection()) {
                Datospersonales oldIddatospersonalesOfUsuarioCollectionUsuario = usuarioCollectionUsuario.getIddatospersonales();
                usuarioCollectionUsuario.setIddatospersonales(datospersonales);
                usuarioCollectionUsuario = em.merge(usuarioCollectionUsuario);
                if (oldIddatospersonalesOfUsuarioCollectionUsuario != null) {
                    oldIddatospersonalesOfUsuarioCollectionUsuario.getUsuarioCollection().remove(usuarioCollectionUsuario);
                    oldIddatospersonalesOfUsuarioCollectionUsuario = em.merge(oldIddatospersonalesOfUsuarioCollectionUsuario);
                }
            }
            for (Solicitudusuario solicitudusuarioCollectionSolicitudusuario : datospersonales.getSolicitudusuarioCollection()) {
                Datospersonales oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario = solicitudusuarioCollectionSolicitudusuario.getIddatospersonales();
                solicitudusuarioCollectionSolicitudusuario.setIddatospersonales(datospersonales);
                solicitudusuarioCollectionSolicitudusuario = em.merge(solicitudusuarioCollectionSolicitudusuario);
                if (oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario != null) {
                    oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario.getSolicitudusuarioCollection().remove(solicitudusuarioCollectionSolicitudusuario);
                    oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario = em.merge(oldIddatospersonalesOfSolicitudusuarioCollectionSolicitudusuario);
                }
            }

            utx.commit();
            addSuccessMessage("La solicitud fue creada con éxito.");
        } catch (Exception ex) {
            try {
                if (findDatospersonales(datospersonales.getIddatospersonales()) != null) {
                    addErrorMessage("El registro " + datospersonales + " ya existe.");
                } else {
                    ensureAddErrorMessage(ex, "ha ocurrido un error en la base de datos.");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Ocurrió un error al intentar restaurar la transacción..");
            }
            return null;
        } finally {
            em.close();
        }
        return detailSetupS();
    }
    
    /**
     * Función de Navegación a la Pagina Details.jsp
     * @return String
     */
    public String detailSetupS() {
        return "datospersonales_details";
    }
    
    /**
     * Función de Navegación a la Pagina Principal
     * @return String
     */
    public String indexSetup() {
        reset(true);
        return "return_inicio";
    }
    
    /**
     * Función de Navegación a la Página Edit.jsp
     * @return String
     */
    public String editSetupAll() {
        return scalarSetupAll("datospersonales_editmyselft");
    }
    /**
     * Metodo para Inicializar parametros de inicio y obtener el Objeto usuario del Context
     * @param destination siguiente JSP a Desplegar
     * @return siguiente JSP pasado como parametro
     */
    private String scalarSetupAll(String destination) {
        reset(false);
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        Usuario user = (Usuario) session.getAttribute("user");
        datospersonales = user.getIddatospersonales();
        datospersonales.setUserAudita(user.getIdUsuario());
        return destination;
    }

    /**
     * Metodo publico para obtener el identificador de Sexo
     * @return una lista con todos tipos de sexo disponibles
     */
    public SelectItem[] getSexsAvailableSelectOne() {
        return getSexsAvailable();
    }

    /**
     * Metodo privado para obtener el identificador de Sexo
     * @return una lista con todos tipos de sexo disponibles
     */
    private SelectItem[] getSexsAvailable() {
        SelectItem[] items = new SelectItem[3];
        items[0] = new SelectItem("","---------");
        items[1] = new SelectItem("M","Masculino(M)");
        items[2] = new SelectItem("F","Femenino(F)");
        return items;
    }    
}
